%{
	#include <stdio.h>
	#include <string.h>
	#include <stdlib.h>
	#include "gr.h"
	#include "checkGr.h"
	  
	grADT * gr = NULL;
	prodADT prod;
	int cGr = 0, nGr = 0;
	int estado=0;
%}

LETRAMAY 	[A-Z]
LETRAMIN	[a-z]
LETRAMINNUM	[a-z0-9]
CARACTER	[A-Za-z0-9]
CARACTER_PROD [A-Za-z0-9\\]
IGUAL 		"="
LLAVE_I 	"{"
LLAVE_D 	"}"
ESPACIO 	[ \t\n]
ESPACIADOR [" "\t\n]
CORCHETE_I 	"("
CORCHETE_D 	")"
COMA		","
FLECHA		"->"
BARRA		"|"

%s NOMBRE
%s INICIO_SIMBOLOS
%s SIMBOLOS_NO_TERMINALES
%s SIMBOLOS_NO_TERMINALES_SEPARADOR
%s SEPARADOR
%s SIMBOLOS_TERMINALES
%s SIMBOLOS_TERMINALES_SEPARADOR
%s SEPARADOR2
%s SIMBOLO_INICIAL
%s SEPARADOR3
%s PRODUCCIONES
%s PRODUCCION_IZQ
%s PRODUCCION_DERIVA
%s FIN

%%


<INITIAL>{ESPACIO}+ {
						gr = realloc(gr,sizeof(grADT) * (cGr + 1));
						gr[cGr]=newGr();
						nGr++;
						BEGIN NOMBRE;
				}
				
<INITIAL>{CARACTER}+ {
						gr = realloc(gr, sizeof(grADT) * (cGr + 1));
						gr[cGr]=newGr();
						nGr++;
						setGrNombre(gr[cGr],yytext);
						BEGIN NOMBRE;
				}

<NOMBRE>{ESPACIO}+ {
					;
				}

<NOMBRE>{CARACTER}+ {
						setGrNombre(gr[cGr],yytext);
						BEGIN NOMBRE;
				}

<NOMBRE>{IGUAL} {
						estado = 1;
						BEGIN INICIO_SIMBOLOS;
				}
				
<INICIO_SIMBOLOS>{ESPACIO}*{CORCHETE_I}{ESPACIO}*{LLAVE_I}{ESPACIO}* {
						/*printf("Simbolos no terminales: ");*/
						BEGIN SIMBOLOS_NO_TERMINALES;
				}

<SIMBOLOS_NO_TERMINALES>{LETRAMAY} {
						addGrSNT(gr[cGr],yytext[0]);
						/*printf("%s\n", yytext);*/
						BEGIN SIMBOLOS_NO_TERMINALES_SEPARADOR;
				}

<SIMBOLOS_NO_TERMINALES_SEPARADOR>{ESPACIO}*{COMA}{ESPACIO}* {
						BEGIN SIMBOLOS_NO_TERMINALES;
				}
				
<SIMBOLOS_NO_TERMINALES_SEPARADOR>{ESPACIO}*{LLAVE_D} {
						BEGIN SEPARADOR;
				}				

				
<SEPARADOR>{ESPACIO}*{COMA}{ESPACIO}*{LLAVE_I}{ESPACIO}* {
						/*printf("Simbolos terminales: ");*/
						estado = 2;
						BEGIN SIMBOLOS_TERMINALES;
				}

<SIMBOLOS_TERMINALES>{LETRAMINNUM} {
						 addGrST(gr[cGr],yytext[0]);
						 /*printf("%s\n", yytext);*/
						 BEGIN SIMBOLOS_TERMINALES_SEPARADOR;
				}

<SIMBOLOS_TERMINALES_SEPARADOR>{ESPACIO}*{COMA}{ESPACIO}* {
						BEGIN SIMBOLOS_TERMINALES;
				}
				
<SIMBOLOS_TERMINALES_SEPARADOR>{ESPACIO}*{LLAVE_D} {
						BEGIN SEPARADOR2;
				}	

<SEPARADOR2>{ESPACIO}*{COMA}{ESPACIO}* {
						/*printf("Simbolo inicial: ");*/
						estado = 3;
						BEGIN SIMBOLO_INICIAL;
				}

<SIMBOLO_INICIAL>{LETRAMAY} {
						/*printf("%s\n", yytext);*/
						BEGIN SEPARADOR3;
				}
				
<SEPARADOR3>{ESPACIO}*{COMA}{ESPACIO}*{LLAVE_I}{ESPACIO}* {
						/*printf("Producciones: \n");*/
						estado = 4;
						prod = newProd();
						BEGIN PRODUCCIONES;
				}
				
<PRODUCCIONES>{ESPACIO}+ {
						BEGIN PRODUCCIONES;
				}

<PRODUCCIONES>{CARACTER}+ {
						/*printf("%s", yytext);*/
						addProdIzq(prod,yytext);
						BEGIN PRODUCCION_IZQ;
				}

<PRODUCCION_IZQ>{ESPACIO}+ {
						BEGIN PRODUCCION_IZQ;
				}

<PRODUCCION_IZQ>{CARACTER}+ {
						/*printf("%s", yytext);*/
						addProdIzq(prod,yytext);
						BEGIN PRODUCCION_IZQ;
				}

<PRODUCCION_IZQ>{FLECHA} {
						/*printf(" Flecha ");*/
						BEGIN PRODUCCION_DERIVA;
				}
				
<PRODUCCION_DERIVA>{ESPACIO}* {
						BEGIN PRODUCCION_DERIVA;
				}
								
<PRODUCCION_DERIVA>{CARACTER_PROD}* {
						addProdDer(prod,yytext);
						/*printf("%s", yytext);*/
						BEGIN PRODUCCION_DERIVA;
				}
				
<PRODUCCION_DERIVA>{ESPACIO}*{BARRA}{ESPACIO}* {
						setProdDerPipe(prod);
						/*printf(" Pipe ");*/
						BEGIN PRODUCCION_DERIVA;
				}
				
				
<PRODUCCION_DERIVA>{ESPACIO}*{COMA}{ESPACIO}* {
						saveGrProd(gr[cGr],prod);
						freeProd(prod);
						prod=newProd();
						/*printf("\n");*/
						BEGIN PRODUCCIONES;
				}

<PRODUCCION_DERIVA>{ESPACIO}*{LLAVE_D}{ESPACIO}* {
						saveGrProd(gr[cGr],prod);
						freeProd(prod); 
						
						BEGIN FIN;
				}

<FIN>{ESPACIO}*{CORCHETE_D}{ESPACIO}* {
						/*printf("\nFIN\n");*/
						cGr++;
						estado=0;
						BEGIN INITIAL;
			}
			
. {
	return 1;
		}

%%
	int main(int argc, char ** argv)
	{
		char * nombreGr, *nombreST, *nombreSNT;
		
		printf("[+]\n\n\nAnalizador de gramáticas\n\n");
		printf("*^^^^^^^^^^^^^^^^^^^^^^^*\n");
		
		if(argc<2){
			printf("\n[WARNING]: Se debe especificar un archivo de entrada. [ ./atlc file.txt ]\n\n\n[+]\n");
			return 1;
		}
		
		FILE * fd;
		fd = fopen(argv[1],"r");
		
		yyin = fd;
		
		int retCode, i;
		
		retCode = yylex();
		if(retCode!=0){
			printf("\n[ERROR]: Ha surgido un error durante el análisis y se ha interrumpido la ejecución. ");
			
			printf("La gramática número \"%d\" contiene caracteres inválidos. \n",cGr+1);
			switch(estado){
				case 0: printf("Se esperaba NOMBRE\n\n\n"); break;
				case 1: printf("Se esperaba SIMBOLOS NO TERMINALES\n\n\n");break;
				case 2: printf("Se esperaba SIMBOLOS TERMINALES\n\n\n");break;
				case 3: printf("Se esperaba SIMBOLO INICIAL\n\n\n");break;
				case 4: printf("Se esperaba PRODUCCIONES\n\n\n");break;
			}  
			printf("Recuerde que el formato es:\n");
			printf("NombreDeLaGramatica = ( {SimbolosNoTerminales}, {SimbolosTerminales}, SimboloInicial, {Producciones})\n");
			printf("\n\n[+]\n");
			for (i = 0; i < nGr; i++) {
				freeGr(gr[i]);
			}
			free(gr);
			fclose(fd);
			return 2;
		}
		

		printf("Resultados:\n");

		for(i=0; i<cGr ; i++){ 
			printf("%d) \n",i+1);
			printf("* Nombre: \n\t\t%s \n",(nombreGr = getGrNombre(gr[i])));
			printf("* SNT: \n\t\t%s \n",(nombreSNT = getGrSNT(gr[i])));
			printf("* ST: \n\t\t%s \n",(nombreST = getGrST(gr[i])));
			printf("* Producciones: \n");
			printProds(gr[i]);
			printf("\n");
			if (validGr(gr[i])) {
				printf("La gramatica es valida\n");
				if (regDer(gr[i])) {
					printf("La gramatica es regular derecha\n");
				} else if (regIzq(gr[i])) {
					printf("La gramatica es regular izquierda\n");
				} else {
					printf("La gramatica no es regular\n");
				}
			} else {
				printf("La gramatica no es valida\n");
			}
			free(nombreGr);
			free(nombreSNT);
			free(nombreST);
			freeGr(gr[i]);
			printf("\n\n");	
		}	
		free (gr);
		fclose(fd);
		return 0;
	}
